package org.infodavid.common.services;

import java.util.List;
import java.util.Locale;

import javax.persistence.PersistenceException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.infodavid.common.dto.ITemplateCategoryListItem;
import org.infodavid.common.dto.ITemplateVersionListItem;
import org.infodavid.common.impl.services.validators.DefaultTemplateCategoryValidator;
import org.infodavid.common.impl.services.validators.DefaultTemplateVersionValidator;
import org.infodavid.common.model.ITemplate;
import org.infodavid.common.model.ITemplateCategory;
import org.infodavid.common.model.ITemplateVersion;
import org.infodavid.common.model.ModelFactory;
import org.infodavid.common.model.criteria.ICategoryCriteria;
import org.infodavid.common.model.criteria.ITemplateVersionCriteria;
import org.infodavid.common.reflect.InstantiationHelper;
import org.infodavid.common.services.exceptions.ServiceException;
import org.infodavid.common.services.validators.IValidator;

/**
 * The Class TemplateService.
 */
public abstract class TemplateService extends
    AbstractEntityService<ITemplateVersionListItem,ITemplateVersion,ITemplateVersionCriteria> {

	/** The singleton. */
	private static final TemplateService SINGLETON;

	/** The TEMPLATE s_ folder. */
	public final String TEMPLATES_FOLDER = "/templates";

	/** The Constant log. */
	private static final Log LOGGER = LogFactory.getLog(TemplateService.class);

	static {
		try {
			SINGLETON = InstantiationHelper.getInstance().newInstance(TemplateService.class);
		}
		catch (final Exception e) {
			LOGGER.fatal("Can not instantiate the " + TemplateService.class.getName(), e);

			throw new Error(e);
		}
	}

	/**
	 * returns the singleton.
	 * @return <code>CityService</code>
	 */
	public static TemplateService getInstance() {
		return SINGLETON;
	}

	/** The category validator. */
	private IValidator<ITemplateCategory> categoryValidator = new DefaultTemplateCategoryValidator();

	/**
	 * Instantiates a new service.
	 */
	protected TemplateService() {
		super(ITemplateVersion.class, new DefaultTemplateVersionValidator(), ModelFactory.getInstance()
		    .getBuilder(ITemplateVersion.class));
	}

	/**
	 * Find last version by name.
	 * @param context the context
	 * @param value the value
	 * @param locale the locale
	 * @return the template version
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract ITemplateVersion findLastVersionByName(IApplicationContext context, String value,
	    Locale locale) throws PersistenceException, ServiceException;

	/**
	 * Find by last version.
	 * @param context the context
	 * @param key the key
	 * @return the template version
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract ITemplateVersion findByLastVersion(IApplicationContext context, Long key)
	    throws PersistenceException, ServiceException;

	/**
	 * Gets the Template.
	 * @param context the context
	 * @param key the key
	 * @return the Template
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract ITemplate getTemplate(IApplicationContext context, long key)
	    throws PersistenceException, ServiceException;

	/**
	 * Find Template by name.
	 * @param contextMock the context mock
	 * @param name the name
	 * @param locale the locale
	 * @return the Template
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract ITemplate findTemplateByName(IApplicationContext contextMock, String name,
	    Locale locale) throws PersistenceException, ServiceException;

	/**
	 * Find category by name.
	 * @param context the context
	 * @param value the value
	 * @return the template category
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract ITemplateCategory findCategoryByName(IApplicationContext context, String value)
	    throws PersistenceException, ServiceException;

	/**
	 * Adds the.
	 * @param context the context
	 * @param value the value
	 * @return the long
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract long addCategory(IApplicationContext context, ITemplateCategory value)
	    throws PersistenceException, ServiceException;

	/**
	 * Find categories.
	 * @param context the context
	 * @param entities the entities
	 * @param criteria the criteria
	 * @return the long
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract long findCategories(IApplicationContext context,
	    List<ITemplateCategoryListItem> entities, ICategoryCriteria criteria)
	    throws PersistenceException, ServiceException;

	/**
	 * Gets the category.
	 * @param context the context
	 * @param key the key
	 * @return the category
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract ITemplateCategory getCategory(IApplicationContext context, long key)
	    throws PersistenceException, ServiceException;

	/**
	 * Gets the category validator.
	 * @return the validator
	 */
	public IValidator<ITemplateCategory> getCategoryValidator() {
		return categoryValidator;
	}

	/**
	 * Removes the category.
	 * @param context the context
	 * @param key the key
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract void removeCategory(IApplicationContext context, long key)
	    throws PersistenceException, ServiceException;

	/**
	 * Sets the category validator.
	 * @param value the new validator
	 */
	public void setCategoryValidator(final IValidator<ITemplateCategory> value) {
		categoryValidator = value;
	}

	/**
	 * Update.
	 * @param context the context
	 * @param value the value
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract void updateCategory(IApplicationContext context, ITemplateCategory value)
	    throws PersistenceException, ServiceException;
}
